package api

import (
	"bytes"
	"context"
	"fmt"
	"sync"

	"dev.ixmxm.top/rms/boot"
	"dev.ixmxm.top/rms/codes"
	"dev.ixmxm.top/rms/dispatcher"
	"dev.ixmxm.top/rms/managers/chargemanager"
	"dev.ixmxm.top/rms/managers/robotmanager"
	"dev.ixmxm.top/rms/managers/usermanager"
	"dev.ixmxm.top/rms/model"
	"dev.ixmxm.top/rms/utils/json"
	"dev.ixmxm.top/rms/utils/log"
	"dev.ixmxm.top/rms/utils/tools"
	"dev.ixmxm.top/rms/utils/websocket"
	"github.com/gin-contrib/pprof"

	"github.com/gin-gonic/gin"

	"io"
	"io/ioutil"
	"net/http"
	"sort"
	"strings"
	"time"

	"github.com/tealeg/xlsx"

	_ "dev.ixmxm.top/rms/docs"
	swaggerFiles "github.com/swaggo/files"
	ginSwagger "github.com/swaggo/gin-swagger"
)

func New() *HttpGateway {
	hg := new(HttpGateway)
	hg.robotStatusPusher = websocket.NewServer()
	hg.taskStatusChangePusher = websocket.NewServer()
	hg.robotPathPusher = websocket.NewServer()
	hg.chargerStatusPusher = websocket.NewServer()
	hg.undoTaskPusher = websocket.NewServer()
	hg.deviceSatusPusher = websocket.NewServer()
	hg.mapRelationPointStatusPusher = websocket.NewServer()
	hg.dispatcher = dispatcher.New(boot.GetMongoClient())

	log.OpenLog("rms-system",
		log.WithFileMaxAge(hg.dispatcher.SystemConfig.LogCfg.LogMaxAge),
		log.WithCaller(),
		log.WithLevel(hg.dispatcher.SystemConfig.LogCfg.LogLevel),
		log.WithFile("."),
		log.AddWriter(boot.NewChannelEncodeWriter(hg.dispatcher.SystemConfig.LogCfg.LogDbLevel, boot.LogChan)))
	return hg
}

type HttpGateway struct {
	robotPathPusher              *websocket.Pusher //机器人路径websocket推送器
	robotStatusPusher            *websocket.Pusher //机器人状态websocket推送器
	taskStatusChangePusher       *websocket.Pusher //机器人任务状态变化websocket推送器
	undoTaskPusher               *websocket.Pusher //未完成任务websocket推送器
	chargerStatusPusher          *websocket.Pusher //充电桩状态websocket推送器
	deviceSatusPusher            *websocket.Pusher //设备(电梯、移动门)状态websocket推送器
	mapRelationPointStatusPusher *websocket.Pusher //所有厂区切换点的状态websocket推送器
	dispatcher                   *dispatcher.DispatchManager
}

func (hg *HttpGateway) Start(port string) {
	gin.DisableBindValidation()
	gin.SetMode(gin.ReleaseMode)
	gin.DefaultWriter = ioutil.Discard
	route := gin.Default()
	pprof.Register(route)
	hg.bind(route)
	route.Use(Cors())

	go hg.PushRobotPath()
	go hg.PushRobotStatus()
	go hg.PushTasktatusChange()
	go hg.PushUndoTask()
	go hg.PushChargerStatus()
	go hg.PushDeviceStatus()
	go hg.PushMapRelationPointStatus()

	go hg.pushTaskFinish()
	go func() {
		err := route.Run(":" + port)
		if err != nil {
			panic(fmt.Sprintf("start gateway error:", err.Error()))
		}
	}()
}

func (hg *HttpGateway) bind(route *gin.Engine) {
	//url := ginSwagger.URL("http://127.0.0.1:8000/swagger/doc.json")
	route.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
	//websocket
	websocket := route.Group("/rms_api/websocket")
	websocket.GET("/robot_path", hg.wsHandler(hg.robotPathPusher))                      //*机器人路径推送,ws
	websocket.GET("/robot_status", hg.wsHandler(hg.robotStatusPusher))                  //*机器人状态推送，ws
	websocket.GET("/task_status_change", hg.wsHandler(hg.taskStatusChangePusher))       //*任务状态变化推送，ws
	websocket.GET("/undo_task", hg.wsHandler(hg.undoTaskPusher))                        //*未完成任务推送，ws
	websocket.GET("/charge_status", hg.wsHandler(hg.chargerStatusPusher))               //*充电桩状态推送，ws
	websocket.GET("/device_status", hg.wsHandler(hg.deviceSatusPusher))                 //*设备(电梯、移动门)状态的推送，ws
	websocket.GET("/switch_area_status", hg.wsHandler(hg.mapRelationPointStatusPusher)) //获得所有厂区切换点状态推送，ws
	//机器人
	robot := route.Group("/rms_api/robot")
	robot.POST("/add_robot_type", HandleRequest(&addRobotTypeParams{}, hg.AddRobotType))                      //*添加机器人类型
	robot.DELETE("/delete_robot_type", HandleRequest(&RobotTypeDeleteParams{}, hg.DeleteRobotType))           //*删除机器人类型
	robot.POST("/save_robot_type", HandleRequest(&saveRobotTypeParams{}, hg.SaveRobotType))                   //*保存机器人类型
	robot.GET("/get_robot_types", HandleRequest(&emptyParams{}, hg.GetRobotTypes))                            //*获取所有机器人类型
	robot.GET("/download_excel_robot_types", HandleRequest_Excel(&emptyParams{}, hg.DownloadExcelRobotTypes)) //*下载所有AGV类型文件(excel文件)
	robot.POST("/upload_excel_robot_types", HandleRequest_File(&emptyParams{}, hg.UploadExcelRobotTypes))     //*上传所有AGV类型文件(excel文件)
	robot.POST("/add_robot", HandleRequest(&addRobotParams{}, hg.AddRobot))                                   //*添加机器人
	robot.POST("/save_robot", HandleRequest(&saveRobotParams{}, hg.SaveRobot))                                //*修改机器人(不可切换地图和启用禁用)
	robot.GET("/get_robots", HandleRequest(&emptyParams{}, hg.GetRobots))                                     //*获得机器人
	robot.POST("/operate_robot", HandleRequest(&robotOperateParams{}, hg.OperateRobot))                       //*机器人操作(启用、禁用、删除)
	robot.POST("/map_switch_robot", HandleRequest(&mapSwitchRobotParams{}, hg.MapSwitchRobot))                //*机器人切换地图
	robot.GET("/get_robot_statuses", HandleRequest(&emptyParams{}, hg.GetRobotStatuses))                      //+获得所有机器人状态
	robot.GET("/get_robot_all_info", HandleRequest(&emptyParams{}, hg.GetRobotAllInfo))                       //+获得所有机器人详细信息
	robot.POST("/send_robots_softstop", HandleRequest(&robotSoftStopParams{}, hg.SendRobotsSoftStop))         //+所有机器人发送软件急停
	robot.POST("/send_robot_err_msg", HandleRequest(&robotBroadcastErrParams{}, hg.SendRobotBroadcastErr))    //车载报错

	//机器人分组
	robotGroup := route.Group("/rms_api/robot_group")
	robotGroup.POST("/add", HandleRequest(&addRobotGroupParams{}, hg.AddRobotGroup))          //*添加机器人分组
	robotGroup.POST("/update", HandleRequest(&updateRobotGroupParams{}, hg.UpdateRobotGroup)) //*更新机器人分组
	robotGroup.DELETE("/delete", HandleRequest(&getRobotGroupParams{}, hg.DeleteRobotGroup))  //*删除机器人分组
	robotGroup.GET("/get", HandleRequest(&getRobotGroupParams{}, hg.GetRobotGroup))           //*获取机器人分组
	robotGroup.GET("/list", HandleRequest(&emptyParams{}, hg.GetAllRobotGroups))              //*获取所有机器人分组
	robotGroup.GET("/robots", HandleRequest(&getGroupRobotsParams{}, hg.GetRobotGroupRobots)) //*获取机器人分组下的机器人

	//任务
	task := route.Group("/rms_api/task")
	task.POST("/add_task", HandleRequest(&addTaskParams{}, hg.AddTask))         //*添加任务(所有任务，包含充电与断电任务)
	task.DELETE("/delete_task", HandleRequest(&getTaskParams{}, hg.DeleteTask)) //+删除一条任务
	task.DELETE("/clear_task", HandleRequest(&emptyParams{}, hg.ClearTask))     //+清空任务
	task.GET("/get_task", HandleRequest(&getTaskParams{}, hg.GetTask))          //*查询一条任务

	task.GET("/get_task_by_time", HandleRequest(&getTaskTimeParams{}, hg.GetByTimeTasks))                           //*查询所有时间
	task.GET("/get_tasks", HandleRequest(&getTasksParams{}, hg.GetTasks))                                           //*查询任务
	task.GET("/get_tasks_by_taskId", HandleRequest(&getTasksByRmsTaskId{}, hg.GetTasksByRmsTaskId))                 //*查询任务,更具RMS任务
	task.GET("/get_tasks_like_maintaskcode", HandleRequest(&getTasksByMainTaskCode{}, hg.GetTasksLikeMainTaskCode)) //*查询任务,模糊住任务编号
	task.GET("/get_tasks_by_keys", HandleRequest(&getTasksByKeys{}, hg.GetTasksByKeys))                             //*查询任务,通过一些keys
	task.GET("/get_subtasks", HandleRequest(&emptyParams{}, hg.GetSubtasks))                                        //*查询所有子任务
	task.GET("/get_subtasks_by_taskid", HandleRequest(&getTaskParams{}, hg.GetSubTasksByTaskId))
	task.GET("/get_task_bindings", HandleRequest(&emptyParams{}, hg.GetTaskBindings))                        //*查询所有任务绑定信息
	task.GET("/get_tasks_by_maintaskcode", HandleRequest(&getTaskStreamParams{}, hg.GetTasksByMainTaskCode)) //*根据主任务编号获取主任务下所有任务信息
	task.POST("/unlock_maintask", HandleRequest(&unlockMainTaskParams{}, hg.UnlockMainTask))                 //*解除机器人主任务绑定
	task.POST("/operate_task", HandleRequest(&operateTaskParams{}, hg.OperateTask))                          //*手动操作任务
	task.POST("/change_task_grade", HandleRequest(&changeTaskGradeParams{}, hg.ChangeTaskGrade))             //*任务优先级更改
	//地图
	m := route.Group("/rms_api/map")
	m.GET("/get_project_names", HandleRequest(&emptyParams{}, hg.GetProjectNames))                            //*获得所有工程名列表
	m.GET("/get_project_slam_maps", HandleRequest(&getProjectParams{}, hg.GetProjectSlamMaps))                //*获得带AGV的工程Slam地图列表
	m.GET("/get_map_names", HandleRequest(&emptyParams{}, hg.GetMapNames))                                    //*获得地图名称列表
	m.GET("/get_base64_maps", HandleRequest(&getMapsParams{}, hg.GetBase64Maps))                              //*获得Base64地图数据
	m.GET("/get_json_maps", HandleRequest(&getMapsParams{}, hg.GetJsonMaps))                                  //+获得json地图数据
	m.POST("/upload_base64_map", HandleRequest(&uploadBase64MapsParams{}, hg.UploadBase64Map))                //*上传Base64地图(XML)
	m.POST("/upload_json_map", HandleRequest(&uploadJsonMapsParams{}, hg.UploadJsonMap))                      //*上传json地图
	m.POST("/upload_file_map", HandleRequest_File(&uploadFileMapsParams{}, hg.UploadFileMap))                 //*上传地图文件(xml文件)
	m.GET("/download_file_map", HandleRequest_File_NoResponse(&downloadFileMapsParams{}, hg.DownloadFileMap)) //*下载地图文件(xml文件)
	m.DELETE("/delete_map", HandleRequest(&mapDeleteParams{}, hg.DeleteMap))                                  //*删除地图
	m.GET("/get_locked_sites", HandleRequest(&emptyParams{}, hg.GetLockedSites))                              //*获得所有锁定站点列表
	m.POST("/operate_site", HandleRequest(&stationOperateParams{}, hg.OperateSite))                           //*站点操作
	m.GET("/get_locked_areas", HandleRequest(&emptyParams{}, hg.GetLockedAreas))                              //*获得所有锁定区域
	m.POST("/operate_area", HandleRequest(&areaOperateParams{}, hg.OperateArea))                              //*区域站点操作
	m.GET("/get_map_relations", HandleRequest(&emptyParams{}, hg.GetMapRelations))                            //*获取所有地图切换信息
	m.POST("/save_map_relation", HandleRequest(&setMapRelationParams{}, hg.SaveMapRelation))                  //*保存区域切换信息
	m.DELETE("/delete_map_relation", HandleRequest(&deleteMapRelationParams{}, hg.DeleteMapRelation))         //*删除地图切换信息
	m.POST("/release_factory_relation", HandleRequest(&releaseFactoryParams{}, hg.ReleaseFactoryRelation))    //+释放，厂区切换AGV占用

	m.GET("/get_overview_json_maps", HandleRequest(&getOverviewMapParams{}, hg.GetOverViewJsonMaps))             //++获得json总览图数据
	m.POST("/upload_overview_json_map", HandleRequest(&uploadOverviewJsonMapParams{}, hg.UploadOverViewJsonMap)) //++上传json总览图
	m.DELETE("/delete_overview_map", HandleRequest(&mapOverviewDeleteParams{}, hg.DeleteOverviewMap))            //++删除总览图根据总览图名称

	//地堆库
	location := route.Group("/rms_api/location")
	location.GET("/get_ground_locations", HandleRequest(&getGroundLocationsByMapNameParams{}, hg.GetGroundLocationsByMapName)) //+ 通过地图名称 获得相关的地堆库数据
	location.GET("/get_all_ground_locations", HandleRequest(&emptyParams{}, hg.GetGroundLocations))                            //+ 通过地图名称 获得相关的地堆库数据
	location.POST("/upload_ground_location", HandleRequest(&uploadGroundLocationParams{}, hg.UploadGroundLocation))            //+上传所有的地堆库数据
	location.DELETE("/delete_ground_location", HandleRequest(&deleteGroundLocationParams{}, hg.DeleteGroundLocationByMapName)) //+删除指定地图上的所有地堆库组
	location.DELETE("/delete_one_location", HandleRequest(&deleteOneLocationParams{}, hg.DeleteOneLocationByMapName))          //+删除单个指定地图上指定地堆库组
	location.POST("/update_ground_location", HandleRequest(&updateOnGroundLocationParams{}, hg.UpdateGroundLocation))          //+更新单个地堆库组

	//充电桩
	charger := route.Group("/rms_api/charger")
	charger.POST("/add_charger", HandleRequest(&saveChargerParams{}, hg.AddCharger))                          //+添加充电桩
	charger.POST("/save_charger", HandleRequest(&saveChargerParams{}, hg.SaveCharger))                        //*保存充电桩
	charger.DELETE("/delete_charger", HandleRequest(&deleteChargerParams{}, hg.DeleteCharger))                //*删除充电桩
	charger.DELETE("/delete_charger_by_siteid", HandleRequest(&GetChargerParams{}, hg.DeleteChargerBySiteid)) //+删除充电桩根据点位信息
	charger.DELETE("/delete_chargers", HandleRequest(&deleteChargersParams{}, hg.DeleteChargers))             //+批量删除充电桩
	charger.GET("/get_chargers", HandleRequest(&emptyParams{}, hg.GetChargers))                               //*获取所有充电桩
	charger.GET("/get_charger", HandleRequest(&GetChargerParams{}, hg.GetCharger))                            //+获取所有充电桩
	charger.POST("/release_charger", HandleRequest(&releaseChargerParams{}, hg.ReleaseCharger))               //*强制释放充电桩
	charger.GET("/get_charger_statuses", HandleRequest(&emptyParams{}, hg.GetChargerStatuses))                //*获取所有充电桩状态信息
	charger.GET("/get_disCharger_cmd", HandleRequest(&emptyParams{}, hg.GetDisChargerCmd))                    //*获取所有断电指令
	//待命点
	standby := route.Group("/rms_api/standby")
	standby.GET("/get_standby_site", HandleRequest(&GetStandbySiteParams{}, hg.GetStandbySite))                                  //+获取待命点信息
	standby.GET("/get_standby_sites", HandleRequest(&emptyParams{}, hg.GetStandbySites))                                         //*获取所有待命点信息
	standby.POST("/save_standby_site", HandleRequest(&saveStandbySiteParams{}, hg.SaveStandbySite))                              //*保存待命点禁用AGV列表
	standby.POST("/save_standby_site_group_list", HandleRequest(&saveStandbySiteGroupListParams{}, hg.SaveStandGroupListbySite)) //*保存待命点允许分组列表
	//电梯和自动门相关
	device := route.Group("/rms_api/device")
	device.POST("/save_elevator", HandleRequest(&setElevatorParams{}, hg.SaveElevator))                    //*保存电梯信息
	device.POST("/save_elevator_level", HandleRequest(&setElevatorLevelParams{}, hg.SaveElevatorLevel))    //+保存电梯设备层信息
	device.POST("/add_elevator_level", HandleRequest(&setElevatorLevelParams{}, hg.AddElevatorLevel))      //+添加电梯设备层信息
	device.DELETE("/delete_elevator", HandleRequest(&elevatorCodeParams{}, hg.DeleteElevator))             //*删除电梯信息
	device.DELETE("/delete_elevator_level", HandleRequest(&elevatorLevelParams{}, hg.DeleteElevatorLevel)) //+删除电梯设备层信息
	device.GET("/get_elevators", HandleRequest(&emptyParams{}, hg.GetElevators))                           //*获取所有电梯信息
	device.GET("/get_elevator", HandleRequest(&elevatorCodeParams{}, hg.GetElevator))                      //+获取电梯信息
	device.GET("/get_map_elevator_codes", HandleRequest(&emptyParams{}, hg.GetMapElevatorCodes))           //+获取所有地图中所有电梯编号
	device.POST("/release_elevator", HandleRequest(&releaseElevatorParams{}, hg.ReleaseElevator))          //*强制释放电梯
	device.POST("/enable_elevator", HandleRequest(&enableElevatorParams{}, hg.EnableElevator))             //*电梯的启用和禁用
	device.POST("/enable_door", HandleRequest(&enableDoorParams{}, hg.EnableDoor))                         //*自动门的启用和禁用
	device.GET("/get_map_door_codes", HandleRequest(&emptyParams{}, hg.GetMapDoorCodes))                   //+获取所有地图中所有自动门编号
	//日志
	log := route.Group("/rms_api/log")
	log.GET("/get_rms_log", HandleRequest(&getRMSLogsParams{}, hg.GetRMSLogs))                               //*获取rms日志
	log.GET("/get_agv_log", HandleRequest(&getRobotsLogsParams{}, hg.GetRobotsLogs))                         //*获取机器人日志
	log.GET("/download_excel_rms_log", HandleRequest_Excel(&getRMSLogsParams{}, hg.DownloadExcelRmsLogs))    //*下载rms日志文件-时间段(excel文件)
	log.GET("/download_excel_agv_log", HandleRequest_Excel(&getRobotsLogsParams{}, hg.DownloadExcelAgvLogs)) //*下载机器人日志文件(excel文件)
	log.DELETE("/delete_all_rms_log", HandleRequest(&emptyParams{}, hg.DeleteAllRmsLog))                     //删除所有的RMS日志
	log.DELETE("/delete_all_agv_log", HandleRequest(&emptyParams{}, hg.DeleteAllAgvLog))                     //删除所有的机器人日志
	//数据统计
	statistics := route.Group("/rms_api/statistics")
	statistics.GET("/get_statistics", HandleRequest(&getStatisticParams{}, hg.GetStatistic))                         //*数据统计
	statistics.GET("/get_charger_statistics", HandleRequest(&getChargerStatisticParams{}, hg.GetRechargerStatistic)) //*统计当天充电次数
	//任务模板
	taskTemplate := route.Group("/rms_api/task_template")
	taskTemplate.GET("/get_task_templates", HandleRequest(&emptyParams{}, hg.GetTaskTemplates))                                  //*获取所有任务模板
	taskTemplate.GET("/get_subtask_templates", HandleRequest(&getSubtaskTemplateParams{}, hg.GetSubtaskTemplates))               //*获取任务模板所有子模板
	taskTemplate.POST("/upload_excel_subtask_templates", HandleRequest_File(&emptyParams{}, hg.UploadExcelSubtaskTemplates))     //*上传所有AGV类型文件(excel文件)
	taskTemplate.POST("/upload_excel_task_templates", HandleRequest_File(&emptyParams{}, hg.UploadExcelTaskTemplates))           //*上传所有AGV类型文件(excel文件)
	taskTemplate.GET("/download_excel_task_templates", HandleRequest_Excel(&emptyParams{}, hg.DownloadExcelTaskTemplates))       //*下载主任务模板(excel文件)
	taskTemplate.GET("/download_excel_subtask_templates", HandleRequest_Excel(&emptyParams{}, hg.DownloadExcelSubTaskTemplates)) //*下载主任务模板(excel文件)
	taskTemplate.POST("/add_task_template", HandleRequest(&SaveTaskTemplateParams{}, hg.AddTaskTemplate))                        //+添加任务模板
	taskTemplate.POST("/add_subtask_template", HandleRequest(&SaveSubtaskTemplateParams{}, hg.AddSubtaskTemplate))               //+添加任务子模板
	taskTemplate.POST("/add_subtask_template_list", HandleRequest(&SaveSubtaskTemplateListParams{}, hg.AddSubtaskTemplateList))  //+添加任务子模板
	taskTemplate.POST("/save_task_template", HandleRequest(&SaveTaskTemplateParams{}, hg.SaveTaskTemplate))                      //*保存任务模板
	taskTemplate.POST("/save_subtask_template", HandleRequest(&SaveSubtaskTemplateParams{}, hg.SaveSubtaskTemplate))             //*保存任务子模板
	taskTemplate.DELETE("/delete_task_template", HandleRequest(&DeleteTaskTemplateParams{}, hg.DeleteTaskTemplate))              //*删除任务模板
	taskTemplate.DELETE("/delete_subtask_template", HandleRequest(&DeleteSubtaskTemplateParams{}, hg.DeleteSubtaskTemplate))     //*删除任务子模板
	//系统
	system := route.Group("/rms_api/system")
	system.GET("/get_system_config", HandleRequest(&emptyParams{}, hg.GetSystemConfig))                                                //*获取系统配置
	system.POST("/save_system_config", HandleRequest(&SaveSystemConfigParams{}, hg.SaveSystemConfig))                                  //*保存系统配置
	system.POST("/save_system_config_log", HandleRequest(&SaveSystemConfig_LogParams{}, hg.SaveSystemConfig_Log))                      //+保存系统配置(日志)
	system.POST("/save_system_config_middleware", HandleRequest(&SaveSystemConfig_MiddlewareParams{}, hg.SaveSystemConfig_Middleware)) //+保存系统配置(中间件)
	system.POST("/save_system_config_online", HandleRequest(&SaveSystemConfig_OnlineParams{}, hg.SaveSystemConfig_Online))             //+保存系统配置(小车上线)
	system.POST("/save_system_config_traffic", HandleRequest(&SaveSystemConfig_TrafficParams{}, hg.SaveSystemConfig_Traffic))          //+保存系统配置(交管策略)
	system.GET("/get_error_codes", HandleRequest(&emptyParams{}, hg.GetErrorCodes))                                                    //*获取并打印所有错误码
	system.GET("/get_versions", HandleRequest(&emptyParams{}, hg.GetVersions))                                                         //*获取版本信息
	//--定时充电相关
	system.GET("/get_all_timer_charger_rule", HandleRequest(&emptyParams{}, hg.GetAllTimerChargerRule))                                //获得所有日充电规则
	system.POST("/add_one_timer_charger_rule", HandleRequest(&SaveSystemConfig_TimerChargerParams{}, hg.AddOneTimerChargerRule))       //添加一个新的日充电规则
	system.POST("/update_one_timer_charger_rule", HandleRequest(&SaveSystemConfig_TimerChargerParams{}, hg.UpdateOneTimerChargerRule)) //更新一个的日充电规则
	system.DELETE("/delete_one_timer_charger_rule", HandleRequest(&SaveSystemConfig_RuleId{}, hg.DeleteTimerChargerRuleById))          //删除一个充电规则

	//传感器
	sensor := route.Group("/rms_api/sensor")
	sensor.GET("/get_robot_sensor_data", HandleRequest(&getSensorDataParams{}, hg.GetRobotSensorData)) //*主动获取机器人外接传感器数据
	sensor.POST("/set_robot_sensor_data", HandleRequest(&setSensorDataParams{}, hg.SetRFIDSensorData)) //设置RFID，传感器数据
	//图片管理
	resource := route.Group("/rms_api/resource")
	resource.GET("/get_resource_picture", HandleRequest(&getResourcePictureParams{}, hg.GetResourcePicture))     //获得所有管理图片picture
	resource.POST("/save_resource_picture", HandleRequest(&saveResourcePictureParams{}, hg.SaveResourcePicture)) //保存资源管理图片资源
	//用户-权限管理
	sysUser := route.Group("/rms_api/sys_user")
	sysUser.POST("/account_verify", HandleRequest(&AccountVerifyParams{}, hg.VerifyUser))              //验证用户
	sysUser.GET("/get_all_sys_user", HandleRequest(&emptyParams{}, hg.GetAllSysUsers))                 //获得所有的用户信息
	sysUser.POST("/add_sys_user", HandleRequest(&SaveUserParams{}, hg.AddSysUser))                     //添加一个新用户
	sysUser.POST("/update_sys_user", HandleRequest(&SaveUserParams{}, hg.UpdateSysUser))               //更新一个用户
	sysUser.DELETE("/delete_sys_user", HandleRequest(&UserAccountParams{}, hg.DeleteSysUserByAccount)) //删除一个用户
	//4g模块授权
	sysUser.GET("/get_author_user", HandleRequest(&emptyParams{}, hg.GetAuthorUser))                                //获得授权用户信息
	sysUser.GET("/get_author_user_switch", HandleRequest(&emptyParams{}, hg.GetAuthorUserSwitch))                   //获得授权用户的开关状态和时间
	sysUser.GET("/get_author_user_timeout", HandleRequest(&emptyParams{}, hg.GetAuthorUserTimeOut))                 //获得授权用户超时的信息
	sysUser.POST("/operate_author_user_switch", HandleRequest(&SaveUserAuthorSwitch{}, hg.OperateAuthorUserSwitch)) //操作授权用户开关状态

}

func (hg *HttpGateway) wsHandler(server *websocket.Pusher) func(c *gin.Context) {
	return func(c *gin.Context) {
		requestID := tools.GenUUID()
		if !c.IsWebsocket() {
			log.ErrorWithContext(c, "connection is not websockets")
			resp := NewResponse(requestID, nil, codes.ErrWebsockets)
			c.JSON(http.StatusNotAcceptable, resp)
			return
		}
		session, errSession := websocket.NewDefaultServerSession(c, c.Writer, c.Request)
		if errSession != nil {
			resp := NewResponse(requestID, nil, errSession)
			c.JSON(http.StatusInternalServerError, resp)
			return
		}
		session.SetReadHandler(hg.readHandler)
		session.SetPingHandler(hg.pingHandler)
		if errAdd := server.AddSession(c, session); errAdd != nil {
			resp := NewResponse(requestID, nil, errAdd)
			c.JSON(http.StatusInternalServerError, resp)
			return
		}
	}
}

//websocket推送小车状态
func (hg *HttpGateway) PushRobotStatus() {
	for {
		status := robotmanager.GetAllRobotStatusFromCache()
		//
		tipCode := hg.dispatcher.UM().GetTipCode()
		data := &RobotStatus_Ws{
			IsSoftStop:    hg.dispatcher.SystemConfig.IsSoftStop,
			TipCode:       tipCode,
			RobotStatuses: status,
		}
		hg.robotStatusPusher.Push(data)
		// log.Warnf("robot_status time %s", time.Now())
		tools.Sleep(0.5)
	}
}

type RobotStatus_Ws struct {
	IsSoftStop    bool                `json:"is_softstop"`    //是否软件急停
	TipCode       usermanager.TipCode `json:"tip_code"`       //提示码
	RobotStatuses []model.RobotStatus `json:"robot_statuses"` //小车状态集合
}

//websocket推送充电桩状态
func (hg *HttpGateway) PushChargerStatus() {
	for {
		chargers := hg.dispatcher.CM().GetAllChargersFromCache(context.TODO())
		chargerStatuses := make([]model.ChargeStatus, 0)
		for _, charger := range chargers {
			item := model.ChargeStatus{}
			info := charger.GetInfo()
			item.MapName = info.MapName
			item.SiteId = info.SiteId
			item.Id = info.Id
			item.Online = charger.GetChargerStatus() != chargemanager.ChargerWaitConnect && charger.GetChargerStatus() != chargemanager.ChargerCommunicationOverTime
			item.Charging = charger.GetStatusWord().IsCharging
			item.ErrCode = uint8(charger.GetStatusWord().Code)
			item.AgvID = charger.GetInfo().AgvID
			item.Current = charger.GetStatusWord().Current
			item.IsStretch = charger.GetStatusWord().IsOut
			chargerStatuses = append(chargerStatuses, item)
		}
		hg.chargerStatusPusher.Push(chargerStatuses)
		tools.Sleep(1.0)
	}
}

func (hg *HttpGateway) readHandler(data string) {
	//fmt.Printf("WebSocket接收到的数据2:%s", data)
}

func (hg *HttpGateway) pingHandler(data string) error {
	//fmt.Printf("WebSocket接收到的ping数据2:%s", data)
	return nil
}

//websocket推送未完成任务
func (hg *HttpGateway) PushUndoTask() {
	for {
		var status []model.TaskStatus
		status = model.TaskRunningStatus()
		status = append(status, model.TaskWaitingStatus()...)
		tasks, _ := hg.dispatcher.TM().GetAllStatusTasksFromDB(context.Background(), status)
		hg.undoTaskPusher.Push(tasks)
		tools.Sleep(1.0)
	}
}

//websocket推送设备状态
func (hg *HttpGateway) PushDeviceStatus() {
	for {
		// var status []model.TaskStatus
		// status = model.TaskRunningStatus()
		// status = append(status, model.TaskWaitingStatus()...)
		//在dm中获得数据
		//
		deviceStatus := hg.dispatcher.DM().GetAllDeviceStatus()
		hg.deviceSatusPusher.Push(deviceStatus)
		tools.Sleep(1.0)
	}
}

//websocket推送厂区切换点状态
func (hg *HttpGateway) PushMapRelationPointStatus() {
	for {
		//1.获取数据
		usedMapRelationPoint := hg.dispatcher.TRM().GetAllMapRelationPointStatus()
		if usedMapRelationPoint != nil {
			//2.发布数据
			hg.mapRelationPointStatusPusher.Push(usedMapRelationPoint)
		} else {
			hg.mapRelationPointStatusPusher.Push([]*interface{}{})
		}

		tools.Sleep(1.0)

	}
}

//API+websocket给中间件推送任务状态(不更新任务完成信号)
// func (hg *HttpGateway) PushTasktatusChange() {
// 	signal := hg.dispatcher.TM().GetStatusUpdateChan()
// 	sendList := make(map[string][]model.Task, 0)
// 	sendLock := sync.RWMutex{}
// 	httpClient := http.Client{Timeout: 5 * time.Second}
// 	go func() {
// 		for {
// 			tools.Sleep(1)
// 			url := fmt.Sprintf("http://%s:%d/efork_api/task_status_change", hg.dispatcher.SystemConfig.MiddlewareCfg.Ip, hg.dispatcher.SystemConfig.MiddlewareCfg.PortApi)
// 			sendList[url] = make([]model.Task, 0)
// 			sendLock.Lock()
// 			for url, tasks := range sendList {
// 				remain := make([]model.Task, 0)
// 				for _, t := range tasks {
// 					//不更新任务完成信号，解决因rms关闭导致任务结束上传中间件失败问题
// 					if t.Status == model.TaskStatusFinish {
// 						continue
// 					}
// 					data := strings.NewReader(json.DumpString(gin.H{"task_id": t.Id, "status": t.Status, "agv_id": t.AgvId}))
// 					resp, err := httpClient.Post(url, "application/json", data)
// 					if err != nil {
// 						log.Errorf("send task signal to callback error:%s", err.Error())
// 						remain = append(remain, t)
// 						break
// 					}
// 					if resp.StatusCode != http.StatusOK {
// 						log.Errorf("send task signal to callback failed,http code:%d", resp.StatusCode)
// 						remain = append(remain, t)
// 						break
// 					}
// 				}
// 				sendList[url] = remain
// 			}
// 			sendLock.Unlock()
// 		}
// 	}()

// 	for t := range signal {
// 		hg.taskStatusChangePusher.Push(t)
// 		//
// 		sendLock.Lock()
// 		for url, _ := range sendList {
// 			sendList[url] = append(sendList[url], t)
// 		}
// 		sendLock.Unlock()
// 	}
// }

//todo 后面使用版本
func (hg *HttpGateway) PushTasktatusChange() {
	signal := hg.dispatcher.TM().GetStatusUpdateChan()
	sendMap := make(map[uint64]model.Task, 0)
	sendLock := sync.RWMutex{}

	go func() {
		for {
			tools.Sleep(1)
			//循环发送任务状态变化
			if len(sendMap) == 0 {
				hg.taskStatusChangePusher.Push([]*interface{}{})
				continue
			} else {
				//过滤数据
				//清空sendList
				sendList := make([]model.Task, 0)
				sendLock.Lock()
				for _, task := range sendMap {
					if task.Status != model.TaskStatusRunning {
						if _, ok := sendMap[task.Id]; ok {
							delete(sendMap, task.Id)
						}
						continue
					}
					sendList = append(sendList, task)
				}
				sendLock.Unlock()
				hg.taskStatusChangePusher.Push(sendList)
			}
		}
	}()

	for t := range signal {
		var task1 model.Task
		tools.Copy(t, &task1)
		sendLock.Lock()
		sendMap[task1.Id] = task1
		sendLock.Unlock()
	}
}

//API给中间件推送任务完成状态
func (hg *HttpGateway) pushTaskFinish() {
	httpClient := http.Client{Timeout: 5 * time.Second}
	for {
		tools.Sleep(0.2)
		tasks, err := hg.dispatcher.TM().GetAllFinishReportTasksFromDB()
		if err != nil {
			log.Errorf("数据库获取已完成未上报的任务出错")
			continue
		}
		if tasks == nil || len(tasks) < 1 {
			continue
		}
		for _, task := range tasks {
			site := ""
			if task.TargetSiteID != task.TargetID {
				site = task.TargetSiteID
			}
			data := strings.NewReader(json.DumpString(gin.H{"task_id": task.Id, "status": task.Status, "agv_id": task.AgvId, "target_id": site, "map_name": task.MapName, "target_layer": task.TargetLayer, "complete_type": task.CompleteType, "old_target_id": task.TargetID}))
			//获取配置的回调地址
			isReport := true
			url := fmt.Sprintf("http://%s:%d/efork_api/task_status_change", hg.dispatcher.SystemConfig.MiddlewareCfg.Ip, hg.dispatcher.SystemConfig.MiddlewareCfg.PortApi)
			// log.Infof("开始给中间件推送任务(%d)完成状态", task.Id)
			resp, err := httpClient.Post(url, "application/json", data)
			if err != nil {
				isReport = false
				// log.Errorf("上报任务(%d)完成失败 error:%s  url:%s", task.Id, err.Error(), url)
				break
			}
			if resp.StatusCode != http.StatusOK {
				isReport = false
				log.Errorf("上报任务(%d)完成返回失败  http code:%d  url:%s data:%v", task.Id, resp.StatusCode, url, data)
				break
			}
			//增加解析返回值，发生错误继续上传
			res, errRead := ioutil.ReadAll(resp.Body)
			defer resp.Body.Close()
			if errRead != nil {
				isReport = false
				log.Errorf("解析中间件返回数据失败:%s", errRead.Error())
				break
			}
			reply := &struct {
				Code    int    `json:"code"`
				Message string `json:"message"`
			}{}
			res = bytes.TrimPrefix(res, []byte("\xef\xbb\xbf"))
			if errBind := json.Bind(res, reply); errBind != nil {
				isReport = false
				log.Errorf("解析中间件返回body数据失败:%s", errBind.Error())
				break
			}
			if reply.Code != 0 {
				isReport = false
				log.Errorf("中间件处理数据失败,code:%d,message:%s", reply.Code, reply.Message)
				break
			}
			if isReport {
				log.Infof("给中间件推送任务(%d)完成状态成功", task.Id)
				hg.dispatcher.TM().SetTaskReportToDB(task.Id)
			}
		}
	}
}

type PathRes []map[string]interface{}

func (x PathRes) Len() int           { return len(x) }
func (x PathRes) Less(i, j int) bool { return x[i]["agv_id"].(string) < x[j]["agv_id"].(string) }
func (x PathRes) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }

//websocket机器人路径推送
func (hg *HttpGateway) PushRobotPath() {
	for {
		allLocals := make(map[string][]string, 0)
		allBlocks := make(map[string][]string, 0)
		gPaths, lPaths := hg.dispatcher.TRM().GetAllPathsFromDB()
		paths := make(PathRes, 0)
		for name, mapLPaths := range lPaths {
			for _, robotLPath := range mapLPaths {
				globalPath := make([][]interface{}, 0)
				for _, gp := range gPaths[name] {
					if gp.Sn == robotLPath.Sn {
						for _, p := range gp.Paths {
							globalPath = append(globalPath, []interface{}{p.PathId, p.Dir})
						}
						break
					}
				}
				localPath := make([]string, 0)
				lockedList := make([]string, 0)
				for _, lp := range robotLPath.Paths {
					if lp.PathId != "0" {
						localPath = append(localPath, lp.PathId)
					}
					lockedList = append(lockedList, lp.AllBlocks().ToIds()...)
				}
				lockedList = append(lockedList, robotLPath.SpecialLocks.ToIds()...)
				//log.Debugf("robot global path:%s --> %s", sn, robotPaths.ToString())
				if len(globalPath) == 0 && len(localPath) == 0 && len(lockedList) == 0 {
					continue
				}
				allLocals[robotLPath.Sn] = localPath
				allBlocks[robotLPath.Sn] = lockedList
				paths = append(paths, gin.H{"agv_id": robotLPath.Sn, "map_name": name, "global_path": globalPath, "local_path": localPath, "locked_list": lockedList})
			}
		}
		sort.Sort(paths)
		//check := func(list map[string][]int) {
		//	for sn0, l0 := range list {
		//		for sn1, l1 := range list {
		//			if sn0 == sn1 {
		//				continue
		//			}
		//			for _, item0 := range l0 {
		//				for _, item1 := range l1 {
		//					if item0 == item1 {
		//						log.Panicf("list is repeat:sn0:%s,sn1:%s,item0:%d,item1:%d", sn0, sn1, item0, item1)
		//					}
		//				}
		//			}
		//		}
		//	}
		//}
		//check(allLocals)
		//check(allBlocks)
		hg.robotPathPusher.Push(paths)
		tools.Sleep(1)
	}
}

// 生成io.ReadSeeker  参数 titleList 为Excel表头，dataList 为数据
func ToExcel(titleList []string, dataList []interface{}) (content io.ReadSeeker) {
	// 生成一个新的文件
	file := xlsx.NewFile()
	// 添加sheet页
	sheet, _ := file.AddSheet("Sheet1")
	// 插入表头
	titleRow := sheet.AddRow()
	for _, v := range titleList {
		cell := titleRow.AddCell()
		cell.Value = v
	}
	// 插入内容
	for _, v := range dataList {
		row := sheet.AddRow()
		row.WriteStruct(v, -1)
	}

	var buffer bytes.Buffer
	_ = file.Write(&buffer)
	content = bytes.NewReader(buffer.Bytes())
	return
}

// 导入Excel
func ImportExcel(xlFile *xlsx.File, allColNum int) [][]string {

	fristSheet := xlFile.Sheets[0]
	fmt.Println("sheet name: ", fristSheet.Name)
	//获得第一行
	titles := fristSheet.Rows[0]
	if len(titles.Cells) != allColNum {
		return nil
	}
	fmt.Print("数据总列数：", len(titles.Cells))
	//声明一个数组
	temp := make([][]string, len(fristSheet.Rows)-1)
	//遍历行读取
	for index, row := range fristSheet.Rows {
		// 遍历每行的列读取
		if index == 0 {
			for _, cell := range row.Cells {
				//生成对象
				text := cell.String()
				fmt.Printf("%20s", text)
			}
			fmt.Printf("\n")
			continue
		}
		var rowData []string
		for _, cell := range row.Cells {
			//生成对象
			text := cell.String()
			rowData = append(rowData, text)
			fmt.Printf("%20s", text)
		}
		temp[index-1] = rowData
		fmt.Print("\n")
	}
	return temp

}
